/**
 *  @file SDLZoomDrawer.cpp
 *
 *  @date 28-nov-2009
 *  @author Ives van der Flaas
 */

#include <SDL_rotozoom.h>
#include <SDL.h>
#include <iostream>
#include "SDLZoomDrawer.h"
#include "SDLSurfaceDeleter.h"

namespace si_sdl
{

SDLZoomDrawer::SDLZoomDrawer():
	fVirtualScreenWidth(8.0),
	fVirtualScreenHeight(6.0)
{
	resize();

}

void SDLZoomDrawer::resize()
{
	const int screenWidthPx = SDL_GetVideoSurface()->w;
	const int screenHeightPx = SDL_GetVideoSurface()->h;


	const double screenRatio = (1.0*screenWidthPx)/(1.0*screenHeightPx);
	const double fieldRatio = fVirtualScreenWidth/fVirtualScreenHeight;

	int marginLeft = 0;
	int marginRight = 0;
	int marginTop = 0;
	int marginBottom = 0;

	if(fabs(screenRatio-fieldRatio) < 0.01) // ratio's are pretty much equal
	{
		fAdjustedScreenHeight = screenHeightPx;
		fAdjustedScreenWidth = screenWidthPx;
	}
	else if(screenRatio > fieldRatio) // screen is too wide, vertical black bars!
	{
		fAdjustedScreenHeight = screenHeightPx;
		fAdjustedScreenWidth = (fVirtualScreenWidth*fAdjustedScreenHeight)/fVirtualScreenHeight;

		marginLeft = (screenWidthPx-fAdjustedScreenWidth+0.5)/2;
		marginRight = marginLeft;
	}
	else if(screenRatio < fieldRatio) // screen is too high, horizontal black bars!
	{
		fAdjustedScreenWidth = screenWidthPx;
		fAdjustedScreenHeight = (fVirtualScreenHeight*fAdjustedScreenWidth/fVirtualScreenWidth);

		marginTop = (screenHeightPx-fAdjustedScreenHeight+0.5)/2;
		marginBottom = marginTop;
	}

	fScreenOffset = si::Vector2(marginLeft, marginTop);




}
void SDLZoomDrawer::drawNoScale(std::tr1::shared_ptr<SDL_Surface> original, const si::Vector2& position)
{
	const si::Vector2 adjustedScreenPos = position + fScreenOffset;

	SDL_Rect offset;
	offset.x = adjustedScreenPos.getX();
	offset.y = adjustedScreenPos.getY();

	SDL_BlitSurface(original.get(), 0, SDL_GetVideoSurface(), &offset);
}

void SDLZoomDrawer::draw(
		std::tr1::shared_ptr<SDL_Surface> original,
		std::tr1::shared_ptr<SDL_Surface>& resized,
		const si::Vector2& virtualSize,
		const si::Vector2& virtualPosition
		)
{
	const double virtualWidthPercentage = virtualSize.getX()/fVirtualScreenWidth;
	const double repRatio = (1.0*original->w)/(1.0*original->h);

	const int realObjectWidth = virtualWidthPercentage*fAdjustedScreenWidth;
	const int realObjectHeight = (1.0*realObjectWidth)/repRatio;

	bool heightResize = (abs(resized->h - realObjectHeight) > 2);
	bool widthResize = (abs(resized->w - realObjectWidth) > 2);

	if(heightResize || widthResize)
	{
		resized = std::tr1::shared_ptr<SDL_Surface>(
						zoomSurface(
								original.get(),
								1.0*realObjectWidth/original->w,
								1.0*realObjectHeight/original->h,
								1),
						SDLSurfaceDeleter());
	}

	const si::Vector2 zeroBasedVirtualPosition(
					virtualPosition.getX()+fVirtualScreenWidth/2,
					virtualPosition.getY()+fVirtualScreenHeight/2);

	const double positionScaleFactorX = 1.0*fAdjustedScreenWidth/fVirtualScreenWidth;
	const double positionScaleFactorY = 1.0*fAdjustedScreenHeight/fVirtualScreenHeight;

	const double nonAdjustedScreenPosX = positionScaleFactorX*zeroBasedVirtualPosition.getX();
	const double nonAdjustedScreenPosY = fAdjustedScreenHeight -
												positionScaleFactorY*zeroBasedVirtualPosition.getY();
	const si::Vector2 adjustedScreenPos =
					si::Vector2(nonAdjustedScreenPosX, nonAdjustedScreenPosY)+fScreenOffset;

	SDL_Rect offset;
	offset.x = adjustedScreenPos.getX();
	offset.y = adjustedScreenPos.getY();

	SDL_BlitSurface(resized.get(), 0, SDL_GetVideoSurface(), &offset);
}

void SDLZoomDrawer::requestRealSizeAndOffset(si::Vector2 virtualSize, si::Vector2&realSize, si::Vector2& offset)
{
	const double virtualWidthPercentage = virtualSize.getX()/fVirtualScreenWidth;
	const double szRatio = (1.0*virtualSize.getX())/(1.0*virtualSize.getY());

	const int realObjectWidth = virtualWidthPercentage*fAdjustedScreenWidth;
	const int realObjectHeight = (1.0*realObjectWidth)/szRatio;

	realSize = si::Vector2(realObjectWidth, realObjectHeight);
	offset = fScreenOffset;

}

si::Vector2 SDLZoomDrawer::requestDrawableRegion() const
{
	return si::Vector2(fAdjustedScreenWidth, fAdjustedScreenHeight);

}
SDLZoomDrawer::~SDLZoomDrawer()
{
	// TODO Auto-generated destructor stub
}

}
